package com.nuoyuan.wx.common.aop;

import com.nuoyuan.wx.common.dto.BaseRespDto;
import com.nuoyuan.wx.common.exception.BizException;
import com.nuoyuan.wx.service.respcode.CommonRespCodeEnum;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;

/**
 * 异常拦截
 */
@Component
@Aspect
public class ProxyExceptionReturnHandler {

	private static final Logger log = LogManager.getLogger(ProxyExceptionReturn.class);

	@Around("execution(* *.*(..)) && @annotation(com.nuoyuan.wx.common.aop.ProxyExceptionReturn)")
	public Object profile(ProceedingJoinPoint pjp) throws Throwable
	{

		String errorMsg = null;
		BaseRespDto result = null;
		if (log.isDebugEnabled())
		{
			log.debug("进入aop：" + pjp.getSignature().toShortString());
		}

		try
		{
			return pjp.proceed();
		}
		catch (IllegalArgumentException ibae)
		{
			errorMsg = "业务参数非法:" + getClass().getSimpleName() + "异常信息：" + ibae.getMessage();
			log.warn(errorMsg, ibae);
			result = getHandlerReuslt(pjp, CommonRespCodeEnum.PARAM_ILLEGAL.getCode(), ibae.getMessage());
		}
		catch (BizException be)
		{
			errorMsg = "系统异常:" + getClass().getSimpleName() + ",异常信息：" + be.getMessage();
			log.warn(errorMsg, be);
			if (be.getAttach() != null)
			{
				result = getHandlerReusltWithData(pjp, be.getErrorCode(),
						be.getMessage(), be.getAttach());
			} else {
				result = getHandlerReuslt(pjp, be.getErrorCode(), be.getMessage());
			}
		}
		catch (Exception e)
		{
			errorMsg = "系统异常:" + getClass().getSimpleName() + ",异常信息：" + e.getMessage();
			log.error(errorMsg, e);
			result = getHandlerReuslt(pjp, CommonRespCodeEnum.SYSTEM_ERROR.getCode(), CommonRespCodeEnum.SYSTEM_ERROR.getMsg());
		}

		return result;
	}

	/**
	 * 获取异常处理结果
	 * @author hzchenya
	 * @param pjp
	 * @param errorCode
	 * @param errorMsg
	 * @return
	 */
	private BaseRespDto getHandlerReuslt(ProceedingJoinPoint pjp, String errorCode, String errorMsg)
	{
		BaseRespDto baseDto = constructMethodReturnInstance(pjp);
		baseDto.setSuccess(false);
		baseDto.setCode(errorCode);
		baseDto.setMsg(errorMsg);
		return baseDto;
	}

	/**
	 * 获取异常处理结果
	 * @author hzchenya
	 * @param pjp
	 * @param errorCode
	 * @param errorMsg
	 * @return
	 */
	private BaseRespDto getHandlerReusltWithData(ProceedingJoinPoint pjp, String errorCode, String errorMsg, Object data)
	{
		BaseRespDto baseDto = constructMethodReturnInstance(pjp);
		baseDto.setSuccess(false);
		baseDto.setCode(errorCode);
		baseDto.setMsg(errorMsg);
		baseDto.setData(data);
		return baseDto;
	}

	/**
	 * 构造被拦截方法的返回对象
	 * @param pjp
	 * @return
	 */
	private BaseRespDto<Object> constructMethodReturnInstance(ProceedingJoinPoint pjp)
	{
		Signature signature = pjp.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		try
		{
			return (BaseRespDto) method.getReturnType().newInstance();
		}
		catch (InstantiationException e)
		{
			log.error("构造被拦截方法返回对象异常[class:" + method.getDeclaringClass().getName() + "method:" + method.getName()
					+ ", returnType:" + method.getReturnType().getName() + "]", e);
			return new BaseRespDto<>(false, CommonRespCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());
		}
		catch (IllegalAccessException e)
		{
			log.error("构造被拦截方法返回对象异常[class:" + method.getDeclaringClass().getName() + "method:" + method.getName()
					+ ", returnType:" + method.getReturnType().getName() + "]", e);
			return new BaseRespDto<>(false, CommonRespCodeEnum.SYSTEM_ERROR.getCode(), e.getMessage());
		}
	}

}
